#pragma once
#include "requestor.hpp"

namespace myrpc
{
    namespace client
    {
        class RpcCaller
        {
            public:
                using ptr=std::shared_ptr<RpcCaller>;
                using JsonAsyncResponse=std::future<Json::Value>;
                using JsonResponseCallback=std::function<void(const Json::Value&)>;
                RpcCaller(const Requestor::ptr &requestor)
                    :_requestor(requestor)
                {}
                //同步请求
                bool call(const BaseConnection::ptr &conn,const std::string &method,const Json::Value &params,Json::Value &result)
                {
                    //组织请求
                    auto req_msg=MessageFactory::create<RpcRequest>();
                    req_msg->setId(UUID::uuid());
                    req_msg->setMethod(method);
                    req_msg->setParams(params);
                    req_msg->setMType(MType::REQ_RPC);

                    //发送请求，通过requestor
                    BaseMessage::ptr rsp_msg;
                    bool ret=_requestor->send(conn,std::dynamic_pointer_cast<BaseMessage>(req_msg),rsp_msg);
                    if(ret==false)
                    {
                        ELOG("同步Rpc请求失败！");
                        return false;
                    }
                    //3.等待响应
                    auto rpc_rsp_msg=std::dynamic_pointer_cast<RpcResponse>(rsp_msg);
                    if(!rpc_rsp_msg)
                    {
                        ELOG("rpc响应，响应向下类型转换失败！");
                        return false;
                    }
                    if(rpc_rsp_msg->rcode()!=RCode::RCODE_OK)
                    {
                        ELOG("rpc请求出错：%s",errReason(rpc_rsp_msg->rcode()).c_str());

                        return false;
                    }
                    result=rpc_rsp_msg->result();
                    return true;

                }
                //异步请求
                bool call(const BaseConnection::ptr &conn,const std::string &method,const Json::Value &params,JsonAsyncResponse &result)
                {
                    //向服务器发送异步回调请求，设置回调函数，回调函数中会传入一个promise对象，在回调函数中去对promise设置数据
                    //1.构造请求信息
                    auto req_msg=MessageFactory::create<RpcRequest>();
                    req_msg->setId(UUID::uuid());
                    req_msg->setMethod(method);
                    req_msg->setMType(myrpc::MType::REQ_RPC);
                    req_msg->setParams(params);

                    //2.设置回调函数,异步rpc请求的回调是为了往promise里设置数据，而回调rpc请求的回调函数是处理收到的数据
                    auto json_promise=std::make_shared<std::promise<Json::Value>>();
                    result=json_promise->get_future();

                    Requestor::RequestCallback cb=std::bind(&RpcCaller::asyncCallback,this,json_promise,std::placeholders::_1);


                    //3.向服务器发送异步回调请求，绑定回调函数
                    bool ret=_requestor->send(conn,std::dynamic_pointer_cast<BaseMessage>(req_msg),cb);
                    if(ret==false)
                    {
                        ELOG("异步Rpc请求失败！");
                        return false;
                    }
                    return true;
                }
                //回调请求
                bool call(const BaseConnection::ptr &conn,const std::string &method,const Json::Value &params,const JsonResponseCallback &cb)
                {
                    auto req_msg=MessageFactory::create<RpcRequest>();
                    req_msg->setId(UUID::uuid());
                    req_msg->setMethod(method);
                    req_msg->setMType(myrpc::MType::REQ_RPC);
                    req_msg->setParams(params);  

                    Requestor::RequestCallback req_cb=std::bind(&RpcCaller::callCallback,this,cb,std::placeholders::_1);
                    bool ret=_requestor->send(conn,std::dynamic_pointer_cast<BaseMessage>(req_msg),req_cb);
                    if(ret==false)
                    {
                        ELOG("回调Rpc请求失败！");
                        return false;
                    }
                    return true;                    
                    
                }
            private:
                void callCallback(const JsonResponseCallback &cb,const BaseMessage::ptr &msg)
                {
                    auto rsp_msg=std::dynamic_pointer_cast<RpcResponse>(msg);
                    if(rsp_msg.get()==nullptr)
                    {
                        ELOG("Rpc响应，向下类型转换失败！");
                        return;
                    }
                    if(rsp_msg->rcode()!=RCode::RCODE_OK)
                    {
                        ELOG("Rpc异步请求出错：%s",errReason(rsp_msg->rcode()).c_str());
                        return;
                    }
                    //回调rpc请求，直接对接收的结果进行处理
                    cb(rsp_msg->result());
                }
                void asyncCallback(std::shared_ptr<std::promise<Json::Value>> promise,const BaseMessage::ptr &msg)
                {
                    auto rsp_msg=std::dynamic_pointer_cast<RpcResponse>(msg);
                    if(rsp_msg.get()==nullptr)
                    {
                        ELOG("Rpc响应，向下类型转换失败！");
                        return;
                    }
                    if(rsp_msg->rcode()!=RCode::RCODE_OK)
                    {
                        ELOG("Rpc异步请求出错：%s",errReason(rsp_msg->rcode()).c_str());
                        return;
                    }
                    promise->set_value(rsp_msg->result());
                }
            private:
                Requestor::ptr _requestor;
        };
    }
}